
namespace Behemoth.SharePoint.Logging {

    using System;
    using System.Configuration;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Text;

    //using Microsoft.Practices.EnterpriseLibrary.Logging;
    //using Microsoft.Practices.EnterpriseLibrary.Common;

    using Microsoft.SharePoint.Administration;

    using Behemoth.SharePoint.Properties;

    /// <summary>
    /// This class sends everything we would normally write to a Debug/Trace into 
    /// the SharePoint logs as well. This is only so useful in some debugging scenarios,
    /// since many SharePoint farms involve multiple WFEs.
    /// </summary>
    //[Configuration.ConfigurationElementType(typeof(Configuration.CustomTraceListenerData))]
    public class SharepointTraceListener : System.Diagnostics.TraceListener /* TraceListeners.CustomTraceListener */ {

        private static Settings settings = new Settings();

        private static SharepointTraceListener _default;
        public static SharepointTraceListener Default {
            get {
                if (_default == null) {
                    _default = new SharepointTraceListener();
                    _default.TraceLog.DefaultCategory = settings.ULSCategoryDebugging;
                    _default.TraceLog.DefaultLevel =
                      (TraceSeverity)Enum.Parse(typeof(TraceSeverity), settings.ULSDefaultListenerLevel, true);
                }
                return _default;
            }
        }

        /// <summary>
        /// Adds a SharepointTraceListener to the collection, ensuring that
        /// we can not add more than one at any time. If none is provided, the default
        /// listener will be used.
        /// </summary>
        /// <param name="listener"></param>
        /// <param name="addToTrace"></param>
        /// <param name="addToDebug"></param>
        public static SharepointTraceListener EnsureListener(bool addToTrace, bool addToDebug) {
            return EnsureListener(Default, addToTrace, addToDebug);
        }
        public static SharepointTraceListener EnsureListener(SharepointTraceListener listener, bool addToTrace, bool addToDebug) {
            if (listener == null)
                listener = Default;
            if (addToTrace)
                EnsureListener(Trace.Listeners, listener);
            if (addToDebug)
                EnsureListener(Debug.Listeners, listener);
            return listener;
        }

        private static void EnsureListener(TraceListenerCollection listeners, SharepointTraceListener listener) {
            foreach (TraceListener existingListener in listeners) {
                if (existingListener.GetType() == typeof(SharepointTraceListener))
                    return;
            }
            listeners.Add(listener);
        }

        private ULSTraceLogging ulsLog = new ULSTraceLogging();
        public ULSTraceLogging TraceLog {
            get { return ulsLog; }
        }

        public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data) {
            // TODO figure out what kind of class/structure LogEntry is, and/or add any other custom types we need to be able to trace here
            /*
            if (data is LogEntry && this.Formatter != null) {
              Write(this.Formatter.Format(data as LogEntry));
            } else {
             */
            Write(data.ToString());
            //}
        }

        public override void Write(string message) {
            ulsLog.Write(message);
        }

        public override void WriteLine(string message) {
            ulsLog.Write(message);
        }

    } // class
} // namespace

